package club.baimahu.pencil.domain.entity.location;

import com.alibaba.fastjson.JSONObject;
import club.baimahu.pencil.domain.entity.tree.LocationTreeNode;
import club.baimahu.pencil.domain.entity.tree.TreeNode;
import lombok.Data;

import java.util.*;

/**
 * 中国地图
 */
@Data
public class ChinaLocationMap {


    static ChinaLocationMap chinaLocationMap;

    List<TreeNode> treeNodeList;
    Map<Long,TreeNode> nodeIdMap;
    Map<String,TreeNode> nodeNameMap;

    //声明为private ， 使外界无法new实例，只能通过静态方法getChinaLocationMap()获得唯一实例
    private ChinaLocationMap(){}


    // Double Check Lock  双重校检锁
    public static ChinaLocationMap  getChinaLocationMap(){

        //1.对象不存在时才准备创建
        if(chinaLocationMap == null){
            //2.锁住所在类对象，保证同一时间只有一个线程进入内部方法
            synchronized (ChinaLocationMap.class){
                //考虑到两个线程排队进入步骤2，第一个线程创建完对象后退出，第二个线程获得锁又进入到这里，这时候应该再次判断对象是否已被上个线程创建好了，是的话就不必重复创建了
                if(chinaLocationMap == null){
                    chinaLocationMap =  new ChinaLocationMap();
                    chinaLocationMap.init();
                    chinaLocationMap.map();
                    return chinaLocationMap;
                }
            }
        }
        return chinaLocationMap;
    }

    private void map(){
        chinaLocationMap.treeNodeList.stream().forEach(x -> {
            chinaLocationMap.nodeIdMap = Optional.ofNullable(nodeIdMap).orElse(new HashMap<>());
            chinaLocationMap.nodeIdMap.put(x.nodeId(),x);
        });

        chinaLocationMap.treeNodeList.stream().forEach(x -> {
            chinaLocationMap.nodeNameMap = Optional.ofNullable(nodeNameMap).orElse(new HashMap<>());
            chinaLocationMap.nodeNameMap.put(x.nodeName(),x);
        });
    }

    public void init(){

        LocationTreeNode l0 = new LocationTreeNode(-1L,"root");

        LocationTreeNode l1 = new LocationTreeNode(100L,"浙江省");
        LocationTreeNode l2 = new LocationTreeNode(101L,"广东省");
        LocationTreeNode l3 = new LocationTreeNode(102L,"云南省");

        LocationTreeNode l11 = new LocationTreeNode(100_100L,"杭州市");
        LocationTreeNode l12 = new LocationTreeNode(100_101L,"绍兴市");
        LocationTreeNode l21 = new LocationTreeNode(101_100L,"广州市");
        LocationTreeNode l31 = new LocationTreeNode(102_100L,"大理市");

        LocationTreeNode l111 = new LocationTreeNode(100_100_100L,"滨江区");
        LocationTreeNode l121 = new LocationTreeNode(100_101_100L,"诸暨县");
        LocationTreeNode l211 = new LocationTreeNode(101_100_100L,"AA区");
        LocationTreeNode l311 = new LocationTreeNode(102_100_100L,"BB区");

        l0.addChildTreeNode(l1);
        l0.addChildTreeNode(l2);
        l0.addChildTreeNode(l3);

        l1.addChildTreeNode(l11);
        l1.addChildTreeNode(l12);
        l2.addChildTreeNode(l21);
        l3.addChildTreeNode(l31);

        l11.addChildTreeNode(l111);
        l11.addChildTreeNode(l121);

        l21.addChildTreeNode(l211);
        l31.addChildTreeNode(l311);

        chinaLocationMap.treeNodeList = Optional.ofNullable(chinaLocationMap.treeNodeList).orElse(new ArrayList<>());
        chinaLocationMap.treeNodeList.add(l0);
        addAll(l0,chinaLocationMap.treeNodeList);
    }

    private void addAll(TreeNode treeNode,List<TreeNode> treeNodeList){
        List<TreeNode> children = treeNode.children();
        if(children != null){
            treeNodeList.addAll(children);
            children.forEach(x -> addAll(x,treeNodeList));
        }
    }

    public static void main(String[] args) {
        ChinaLocationMap chinaLocationMap = ChinaLocationMap.getChinaLocationMap();
        System.out.println(JSONObject.toJSONString(chinaLocationMap.nodeIdMap));
        System.out.println(chinaLocationMap.nodeNameMap);
        System.out.println(chinaLocationMap.treeNodeList);
    }


}
